const formidable = require('formidable');
const path = require('path');
const mkdirp = require('mkdirp');

/**
 * @apiDefine ErrorResponse
 * @apiError (请求错误) {String} err_message 错误信息描述
 */

/**
 * @apiVersion 1.0.0
 * @apiGroup 文件上传
 * @api {POST} api/upload 文件上传
 * @apiName api/upload
 * @apiExample {js} axios 例子:
 *  const form = new FormData();
 *  const files = e.target.files;
 * 
 *  // 上传单个文件
 *  form.append(files[0].name, files[0]);
 *  // 上传多个文件
 *  files.forEach(file => {
 *    form.append(file.name, file);
 *  })
 * 
 *  axios.post('http://39.105.38.34:8080/api/upload', form).then(res => {
 *    // 上传后的文件通过静态资源服务器提供访问，访问方式是 http://39.105.38.34:8080/files/文件名
 * 
 *    // 上传成功后 res.data.data 是一个数组，数组中的每一项是一个文件名，访问图片的方式见上方；
 *  });
 * 
 * @apiHeader {String} authorization 用户登录或注册成功时返回的 token
 * @apiParam {Object} form JS 的FormData 的实例
 * @apiSuccess (请求成功) {String[]} filenames 如果是上传多个文件，返回一个文件名数组;
 * @apiuse  ErrorResponse
 */

const uploadHandle = (ctx, filepath) => new Promise((resolve, reject) => {
  const form = new formidable.IncomingForm();

  // 设置上传文件的文件夹地址
  form.uploadDir = filepath;
  // 保留上传上来文件的扩展名（ 比如 .jpg, .png 之类的就叫扩展名 ）
  form.keepExtensions = true;
  // 设置是否支持上传多个文件
  form.multiples = true;
  // 设置上传的文件的大小的最大限制；
  form.maxFieldsSize = 1024 * 1024 * 1024;

  // form.parse 解析请求, 将请求中携带的文件处理好，在第二个参数回调函数中可以获取到
  form.parse(ctx.req, (err, fields, files) => {
    if (err) reject(new Error('文件上传失败'));
    resolve(files)
  });
})

module.exports = async (ctx) => {
  const filepath = path.join(__dirname, '../../public/files/')

  // mkdirp 的作用是，如果有对应文件夹则跳过，如果没有则创建对应路径的文件夹
  await mkdirp(filepath);

  try {
    var files = await uploadHandle(ctx, filepath);
    var files = Object.values(files);

    ctx.body = {
      data: files.map(file => path.basename(file.path))
    }
  } catch(e) {
    throw new Error('上传文件失败');
  }
}